#ifndef IEDITOR_ITEM_H
#define IEDITOR_ITEM_H

#include "../graphs/iedgedata.h"
#include "../graphs/inodedata.h"
#include "../serialization/iserializable.h"
#include "../utils/ipropertyobject.h"

#include <QtCore/QList>
#include <QtCore/QRectF>

QT_BEGIN_NAMESPACE
class QPixmap;
class QUuid;
QT_END_NAMESPACE

namespace core
{
class IGraphicItemContent;
class IEditorItem;
class IDocumentData;
class Palette;

class ConnectionData : public IEdgeData
{
public:
    ConnectionData(unsigned int conId, IEditorItem* connector = 0,
        IEditorItem* from = 0, IEditorItem* to = 0) :
            ConnectionId(conId), Connector(connector), From(from), To(to),
            m_edge(0)
    {
    }

    bool operator==(const ConnectionData& other) const
    {
        bool ret = ConnectionId == other.ConnectionId &&
            Connector == other.Connector && From == other.From &&
            To == other.To;

        return ret;
    }

    // IEdgeData
    void registerEdge(Edge* edge)
    {
        m_edge = edge;
    }

    const Edge* const edge() const
    {
        return m_edge;
    }

public:
    unsigned int ConnectionId;
    IEditorItem* Connector;
    IEditorItem* From;
    IEditorItem* To;

private:
    Edge* m_edge;
};

class ConnectionComparator
{
public:
    enum CompareType
    {
        Full = 0x0,
        WithoutConnector = 0x1,
        WithoutConnectionType = 0x2,
        WithoutDirection = 0x4
    };

public:
    static bool compare(const ConnectionData& first,
        const ConnectionData& second, int typeFlags = 0x0)
    {
        bool ret = true;

        if (typeFlags == 0)
        {
            ret = first == second;
        }
        else
        {
            const bool co = (typeFlags & WithoutConnector) ==
                WithoutConnector;
            const bool ct = (typeFlags & WithoutConnectionType) ==
                WithoutConnectionType;
            const bool di = (typeFlags & WithoutDirection) ==
                WithoutDirection;

            ret = (co ? true : first.Connector == second.Connector) &&
                (ct ? true : first.ConnectionId == second.ConnectionId) &&
                (di ? ((first.From == second.From && first.To == second.To) ||
                    (first.From == second.To && first.To == second.From)) :
                (first.From == second.From && first.To == second.To));
        }

        return ret;
    }

private:
    ConnectionComparator() {}
};

enum ThumbnailRole
{
    GalleryRole,
    DragAndDropRole
};

enum ConnectionDirection
{
    Incoming,
    Outgoing,
    Self
};

class IEditorItem : public ISerializable, public IPropertyObject
{
public:
    virtual bool supportsConnection(
        const ConnectionData& connection) const = 0;
    virtual QList<ConnectionData> connections() const = 0;
    virtual void connectionsRefreshed() = 0;

    virtual IEditorItem* parentEditorItem(IEditorItem* parent) const = 0;
    virtual void setParentEditorItem(IEditorItem* parent) = 0;

    virtual IDocumentData* parentDocumentData() const = 0;
    virtual void setParentDocumentData(IDocumentData* data) = 0;

    virtual bool isModel() const = 0;
    virtual bool isGraphic() const = 0;
    virtual bool isText() const = 0;

    virtual int type() const = 0;

    virtual QUuid id() const = 0;

    virtual QString name() const = 0;

    virtual IEditorItem* copy() const = 0;

    virtual ~IEditorItem() {}
};

class IModelEditorItem : public IEditorItem
{
public:
    virtual ~IModelEditorItem() {}
};

enum PaletteType
{
    Background = 0x01,
    Border = 0x02,
    Whole = 0x04
};

class IGraphicEditorItem : public IEditorItem, public INodeData
{    
public:
    virtual QPixmap thumbnail(ThumbnailRole role,
        int size = -1) const = 0;

    virtual void editorModeChange() = 0;

    virtual void setContent(IGraphicItemContent* content) = 0;

    virtual IGraphicItemContent* content() const = 0;

    virtual void setPalette(const Palette* const palette) = 0;

    virtual int paletteType() const = 0;

    virtual void scaleToFitContent() = 0;

    virtual void handleContentRefresh() = 0;

    virtual void handleConnectorPositionChange() = 0;

    virtual void handleSelfConnect(core::IGraphicEditorItem* connector,
        const QPointF& cursorPos, bool previousSelfConnect = false) = 0;

    virtual void ensureHandlesGeometryChanges(bool enabled) = 0;

    virtual QPointF nearestConnectionPoint(const QPointF& to,
        ConnectionDirection direction) const = 0;

    virtual void handleSceneResize() = 0;

    virtual void arrangeConnectorsRequest() = 0;

    virtual bool canBeDuplicated() const = 0;

    virtual ~IGraphicEditorItem() {}
};

class ITextEditorItem : public IEditorItem
{
public:
    virtual ~ITextEditorItem() {}
};

} // namespace core

uint qHash(const core::ConnectionData& data);

#endif
